package cn.itzd.config;

import cn.itzd.filter.MyAccessDeniedHandler;
import cn.itzd.filter.MyAuthenticationEntryPoint;
import cn.itzd.filter.MyJwtAuthenticationTokenFilter;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.io.IOException;

/**
 * @Author: dada
 * @Version: 1.0
 * @Description:
 */
@Configuration
@EnableWebSecurity // 原先的配置
@EnableGlobalMethodSecurity(prePostEnabled = true)  // 注解
public class SecurityConfig {

    /**
     * 权限过滤
     */
    @Autowired
    private MyAccessDeniedHandler accessDeniedHandler;

    /**
     * 登录过滤
     */
    @Autowired
    private MyAuthenticationEntryPoint authenticationEntryPoint;

    /**
     * token过滤
     */
    @Autowired
    private MyJwtAuthenticationTokenFilter myJwtAutowiredEncoder;

    /**
     * 放行接口
     */
    private static final String[] URL_WHITELIST = {
            "/code",
            "/login",
            "/test",
            "/reg",
            "/profile/**",
            "/upload",
    };

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private AuthenticationConfiguration authenticationConfiguration;

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        AuthenticationManager authenticationManager = authenticationConfiguration.getAuthenticationManager();
        return authenticationManager;
    }


    @Bean
    public SecurityFilterChain securityChain(HttpSecurity http) throws Exception {
        //过滤器配置
        http.addFilterBefore(myJwtAutowiredEncoder, UsernamePasswordAuthenticationFilter.class);

        http.authorizeHttpRequests(authorizeHttpRequests->
                authorizeHttpRequests.requestMatchers(URL_WHITELIST).permitAll()
                        .anyRequest().authenticated()
        );
        http.cors(cors->cors.configurationSource(configurationSource()));
        //异常处理
        http.exceptionHandling(exceptionHandling->exceptionHandling.accessDeniedHandler(accessDeniedHandler).authenticationEntryPoint(authenticationEntryPoint));
        //全局禁用session
        http.sessionManagement(sessionManagement->sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
        //关闭浏览器跨域请求
        http.csrf(AbstractHttpConfigurer::disable);

        return http.build();
    }

    //配置跨域
    private CorsConfigurationSource configurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOriginPattern("*");
        corsConfiguration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
        return urlBasedCorsConfigurationSource;
    }
}
